#! /usr/bin/env python
"""datetime helpers

Copyright (C) 2011-2014 Christian T. Steigies <steigies@physik.uni-kiel.de>

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
"""

__author__ = "Christian T. Steigies <steigies@physik.uni-kiel.de>"
__license__ = "GPL License"

from datetime import datetime, date, time, timedelta
from time import gmtime, strftime

## --------------------------------------------------------------------------
#import MySQLdb # python-mysqldb


## --------------------------------------------------------------------------
def valid_date(year, month, day):
    """return True if data is a valid data, False if not"""

    try:
        datetime(year, month, day)
    except TypeError:
        print "TypeError in date:", year, month, day
        return False
    except ValueError:
        return False
    return True

## --------------------------------------------------------------------------
def sys_timestamp(format="dt"):
    """get system time in UTC"""

    now = gmtime()
    if format in ["dt", "datetime"]:
        value = datetime(now.tm_year, now.tm_mon, now.tm_mday, now.tm_hour, now.tm_min, now.tm_sec)
    elif format in ["str", "string"]:
        value = strftime("%Y-%m-%d %H:%M:%S", gmtime())
    else:
        raise ValueError  # unknown format
    return value

## --------------------------------------------------------------------------
def year2(year):
    """return last two digits of year"""
    return year % 100

## --------------------------------------------------------------------------
def last_datapoint(cursor, table, station):
    """return timestamp of last value for station in real-time table"""
    
    if table in ["1m"]:  # 1m real-time data is in ori table
        table = "ori"
    elif table in ["ori", "1h", "env", "meta"]:
        pass
    elif table in ["rev"]:
        raise ValueError  # rev is not a real-time table
    else:
        raise ValueError  # illegal table

    querystring = "SELECT start_date_time FROM %s_%s ORDER BY start_date_time DESC LIMIT 1;" % (station.upper(), table)
    cursor.execute(querystring)
    answer = cursor.fetchone()
    if answer == None:
        print "%s_%s is empty, you should select a --startdate. Using default date." % (station.upper(), table)
        #lastdatapoint = datetime(1910, 12, 31, 0, 0, 0)
        lastdatapoint = datetime(2013, 10, 03, 0, 0, 0)
    else:
        lastdatapoint = answer[0]
    return(lastdatapoint)

## --------------------------------------------------------------------------
def read_datapoint(cursor, table, station, timestamp, values="*"):
    """return values for station in table at timestamp"""
    
    querystring = "SELECT %s FROM %s_%s WHERE start_date_time = \"%s\";" % (values, station.upper(), table, timestamp)
    cursor.execute(querystring)
    answer = cursor.fetchone()
    return(answer)

## --------------------------------------------------------------------------
def str2date(string):
    """convert string into datetime date"""

    if string:
        (year, month, day) = string.split("-")
        timestamp = date(int(year), int(month), int(day))

        return timestamp
    else:
        raise ValueError

## --------------------------------------------------------------------------
def str2time(string):
    """convert string into datetime time"""

    if string:
        (hour, minute, sec ) = string.split(":")
        timestamp = time(int(hour), int(minute), int(sec))

        return timestamp
    else:
        raise ValueError

## --------------------------------------------------------------------------
def str2datetime(string):
    """convert string into datetime timestamp"""
    
    if string:        
        # datetime.strptime is not available on CentOS
        #dt = datetime.strptime(s, "%Y-%m-%d %H:%M:%S")

        (mydate, mytime) = string.split()
        (year, month, day) = mydate.split("-")
        (hour, minute, sec ) = mytime.split(":")
        timestamp = datetime(int(year), int(month), int(day), int(hour), int(minute), int(sec))
        
        return timestamp
    else:
        raise ValueError
    
## --------------------------------------------------------------------------
def parse_date(line):
    """parse input data
NEWK_QL_Minute.txt; yyyyy-mn-dom^hh:mm:ssTcorrTpressTuncorr; ^ = space, T = tab^M
NEWK_Minute.txt;    yyyyy-mn-dom^hh:mm:ssTcorrTpressTuncorr; ^ = space, T = tab^M

    format: yyyy-mm-dd hh:mm:ss or yyyy mm dd hh:mm:ss
            0123456789012345678"""
    
    #print "spaces:", line.count(" ")
    if (line.find(" ", 10) == 10):
        #print "SPACE found after date"
        pass
    else:
        #print "illegal data format"
        raise ValueError # SPACE not found after data

    mydate = line[:10]
    if (mydate.find("-") == 4): # after 4 digit year either -
        #print "- found after year"
        sep = "-"
    elif (mydate.find(" ") == 4): # or SPACE separates the month
        #print "SPACE found after year"
        sep = " "
    else:
        raise ValueError # separator not found after year

    if (mydate.find(sep, 5) == 7): # day is separated from month
        #print "sep found after month"
        year  = int(mydate.split(sep)[0])
        month = int(mydate.split(sep)[1])
        day   = int(mydate.split(sep)[2])
    else:
        raise ValueError # separator not found after month    
        
    if (line.find(" ", 19) == 19):
        #print "SPACE found after time"
        pass
    elif (line.find("\t", 19) == 19):
        #print "TAB found after time"
        pass
    else:
        #print "illegal time format"
        raise ValueError # no SPACE or TAB found after time

    time = line[11:19]
    if (time.find(":") == 2): # after 2 digit hout either :
        #print ": found after hour"
        sep = ":"
    elif (time.find(" ") == 2): # or SPACE separates the minute
        #print "SPACE found after hour"
        sep = " "
    else:
        raise ValueError # separator not found after hour

    if (time.find(sep, 4) == 5): # second is separated from minute
        #print "sep found after minute"
        hour   = int(time.split(sep)[0])
        minute = int(time.split(sep)[1])
        second = int(time.split(sep)[2])
    else:
        raise ValueError # separator not found after month
    
    rest = line[19:] # return the remaining data as-is
    # data is given as: corr press uncorr with TABs separating the fields:
    #corr = float(d.split()[0])
    #press  = float(d.split()[1])
    #uncorr   = float(d.split()[2])

    # return data in order of processing: uncorrected + pressure -> corrected
    #return(year, month, day, hour, minute, second, [uncorr, press, corr])
    return(year, month, day, hour, minute, second, rest)

## --------------------------------------------------------------------------
def date2doy(mydate):
    """convert date to doy"""
    # use timedelta
    value = (mydate - date(mydate.year, 1, 1)).days + 1
    # use ordinal
    #value = mydate.toordinal() - date(mydate.year, 1, 1).toordinal() + 1

    return value
                                                            
## --------------------------------------------------------------------------
def doy2date(year, doy):
    """convert doy to date"""

    value = date.fromordinal(date(year, 1, 1).toordinal() + doy - 1)

    return value

## --------------------------------------------------------------------------
def mod2time(mod):
    """convert minute-of-day to time"""

    hour = int(mod/60)
    minute = mod - 60*hour
    value = time(hour, minute)

    return value

## --------------------------------------------------------------------------
def calgary_dt(year, doy, hour, end_min, resolution=300):
    """
    convert calgary data to datetime
    dt is give as end of measurement, so all data needs to be shifted
    """

    if hour == 24:
        # reduce hour by one, delta by 3600 seconds to compensate
        hour = 23 
        delta = timedelta(0, resolution - 3600)
    else:
        delta = timedelta(0, resolution)
        
    mydate = doy2date(year, doy)
    mytime = time(hour, end_min)

    value = datetime.combine(mydate, mytime) - delta

    return value    
## --------------------------------------------------------------------------
if __name__ == "__main__":
    print "This is the tools.datetool module."

    for myday in xrange(1, 366):
        myd = doy2date(2016, myday)
        print myd, myd.year, myd.month, myd.day, "\tDOY:", date2doy(myd)
    exit(0)
    #data =["2011 10 13 21:06:00     107.43  749.30  119.85",
    #        "2011-10-30 08:50:00     94.71   759.40  95.31"]
    data = ["2011-10-30 08:50:00     94.71   759.40  95.31"]
    for lines in data:
        #print parse_date(lines)
        print lines
        if 0:
            (y, m, d, H, M, S, dat) = parse_date(lines)
            print "y:%i m:%i d:%i H:%i M:%i S:%i: data:%s" % (y, m, d, H, M, S, dat)
        else:
            s = lines[:19]
            print s
            print str2datetime(s)
